package par

import (
	"testing"

	"gitcode.com/deyiyangyang/gascheme/ast"
	"gitcode.com/deyiyangyang/gascheme/eva"
	"gitcode.com/deyiyangyang/gascheme/lex"
	"gitcode.com/deyiyangyang/gascheme/obj"
)

func TestStringLiteralParsingp(t *testing.T) {
	tests := []struct {
		input    string
		expected string
		tokenLiteral string
	}{{
		input:    `"hello world"`,
		expected: "hello world",
		tokenLiteral: "hello world",
	}, {
		input:    `""`,
		expected: "",
		tokenLiteral: "",
	}, {
		input:    `"a string with spaces"`,
		expected: "a string with spaces",
		tokenLiteral: "a string with spaces",
	}, {
		input:    `"\""`,
		expected: "\"",
		tokenLiteral: "\\\"",
	}, {
		input:    `"string with \"quotes\" inside"`,
		expected: "string with \"quotes\" inside",
		tokenLiteral: "string with \\\"quotes\\\" inside",
	},
	}

	for _, tt := range tests {
		lexer := lex.NewLexer(tt.input)
		parser := NewParser(lexer)
		expr, err := parser.ParseExpression()
		if err != nil {
			t.Fatalf("Parse error: %s", err)
		}

		strLit, ok := expr.(*ast.StringLiteral)
		if !ok {
			t.Fatalf("Expression is not a StringLiteral. Got: %T", expr)
		}

		if strLit.Value != tt.expected {
			t.Errorf("String value wrong. Expected: %s, Got: %s", tt.expected, strLit.Value)
		}

		if strLit.TokenLiteral() != tt.tokenLiteral {
			t.Errorf("Token literal wrong. Expected: %s, Got: %s", tt.tokenLiteral, strLit.TokenLiteral())
		}
	}
}

func TestStringInListParsing(t *testing.T) {
	input := `("hello" "world")`
	lexer := lex.NewLexer(input)
	parser := NewParser(lexer)
	expr, err := parser.ParseExpression()
	if err != nil {
		t.Fatalf("Parse error: %s", err)
	}

	list, ok := expr.(*ast.ListExpression)
	if !ok {
		t.Fatalf("Expression is not a ListExpression. Got: %T", expr)
	}

	if len(list.Elements) != 2 {
		t.Fatalf("List has wrong length. Expected: 2, Got: %d", len(list.Elements))
	}

	str1, ok := list.Elements[0].(*ast.StringLiteral)
	if !ok {
		t.Fatalf("First element is not a StringLiteral. Got: %T", list.Elements[0])
	}

	if str1.Value != "hello" {
		t.Errorf("First string value wrong. Expected: hello, Got: %s", str1.Value)
	}

	str2, ok := list.Elements[1].(*ast.StringLiteral)
	if !ok {
		t.Fatalf("Second element is not a StringLiteral. Got: %T", list.Elements[1])
	}

	if str2.Value != "world" {
		t.Errorf("Second string value wrong. Expected: world, Got: %s", str2.Value)
	}
}

func TestStringEvaluation(t *testing.T) {
	tests := []struct {
		input    string
		expected string
	}{{
		input:    `"hello world"`,
		expected: "hello world",
	}, {
		input:    `""`,
		expected: "",
	},
	}

	for _, tt := range tests {
		lexer := lex.NewLexer(tt.input)
		parser := NewParser(lexer)
		expr, err := parser.ParseExpression()
		if err != nil {
			t.Fatalf("Parse error: %s", err)
		}

		env := obj.NewEnvironment()
		result := eva.Eval(expr, env)
		strObj, ok := result.(*obj.String)
		if !ok {
			t.Fatalf("Result is not a String object. Got: %T", result)
		}

		if strObj.Value != tt.expected {
			t.Errorf("String value wrong. Expected: %s, Got: %s", tt.expected, strObj.Value)
		}

		if strObj.Type() != obj.STRING_OBJ {
			t.Errorf("Object type wrong. Expected: %s, Got: %s", obj.STRING_OBJ, strObj.Type())
		}
	}
}
